"""截图工具模块"""

import logging
import sys
import tkinter as tk
from tkinter import messagebox

from PIL import ImageGrab


def capture_screenshot(region=None):
    """
    截取屏幕截图
    
    Args:
        region (tuple): 截图区域 (left, top, right, bottom)
        
    Returns:
        PIL.Image: 截图图像
    """
    try:
        if region:
            # 确保坐标是整数类型并且有效
            bbox = tuple(int(x) for x in region)
            if len(bbox) != 4:
                raise ValueError("区域坐标必须包含4个值")
            # 检查坐标有效性
            left, top, right, bottom = bbox
            if left >= right or top >= bottom:
                raise ValueError("区域坐标无效")
            screenshot = ImageGrab.grab(bbox=bbox)
        else:
            screenshot = ImageGrab.grab()
        return screenshot
    except Exception as e:
        logging.error(f"截图时出错: {e}")
        return None


class ScreenshotSelector:
    """截图区域选择器"""

    def __init__(self):
        self.start_x = None
        self.start_y = None
        self.end_x = None
        self.end_y = None
        self.drawing = False
        self.screenshot = None
        self.root = None
        self.canvas = None
        self.rect = None
        self.coord_label = None
        self.selection_made = False  # 标记是否已经完成选择
        self.overlay = None  # 半透明蒙版
        self.selection_rect = None  # 选择区域矩形
        self.crosshair_h = None  # 水平十字线
        self.crosshair_v = None  # 垂直十字线

    def select_region(self):
        """
        通过GUI选择截图区域
        
        Returns:
            tuple: 截图区域 (left, top, right, bottom) 或 None
        """
        try:
            # 创建全屏窗口
            self.root = tk.Tk()
            self.root.title("选择截图区域")

            # 获取屏幕尺寸
            screen_width = self.root.winfo_screenwidth()
            screen_height = self.root.winfo_screenheight()

            # 确保尺寸有效
            if screen_width <= 0 or screen_height <= 0:
                raise ValueError("无法获取屏幕尺寸")

            # 设置窗口为全屏模式
            if sys.platform == "win32":
                # Windows平台特殊处理
                self.root.geometry(f"{screen_width}x{screen_height}+0+0")
                self.root.overrideredirect(True)  # 去除窗口边框
            else:
                self.root.attributes('-fullscreen', True)

            # 设置窗口背景色和透明度
            self.root.configure(bg='black')
            self.root.attributes('-alpha', 0.3)  # 30%透明度，让用户能看到屏幕内容但有明显区别

            # 确保窗口始终在最前面
            self.root.attributes('-topmost', True)

            # 隐藏鼠标指针
            self.root.config(cursor="none")

            # 创建画布
            self.canvas = tk.Canvas(self.root,
                                    width=screen_width,
                                    height=screen_height,
                                    highlightthickness=0)
            self.canvas.pack(fill="both", expand=True)

            # 添加半透明蒙版
            self.overlay = self.canvas.create_rectangle(
                0, 0, screen_width, screen_height,
                fill='#000000',  # 使用十六进制颜色值
                outline=''
            )

            # 添加标题 - 统一字体设置
            self.canvas.create_text(
                screen_width // 2, 50,
                text="屏幕截图区域选择工具",
                fill="white",
                font=("宋体", 20),
                tags="title"
            )

            # 添加操作说明 - 统一字体设置
            instruction_text = (
                "操作说明:\n"
                "1. 按住鼠标左键并拖拽以选择截图区域\n"
                "2. 释放鼠标完成选择并确认\n"
                "3. 按ESC键取消操作"
            )

            self.canvas.create_text(
                screen_width // 2, screen_height // 2 - 50,
                text=instruction_text,
                fill="white",
                font=("宋体", 14),
                tags="instruction"
            )

            # 添加坐标显示标签（初始为空）- 统一字体设置
            self.coord_label = self.canvas.create_text(
                screen_width // 2, screen_height - 100,
                text="区域大小: 0 x 0 像素",
                fill="yellow",
                font=("宋体", 12),
                tags="coordinates"
            )

            # 添加提示信息 - 统一字体设置
            self.canvas.create_text(
                screen_width // 2, screen_height - 50,
                text="请开始拖拽选择区域...",
                fill="cyan",
                font=("宋体", 12),
                tags="hint"
            )

            # 创建十字线
            self.crosshair_h = self.canvas.create_line(0, 0, screen_width, 0, fill="white", width=1)
            self.crosshair_v = self.canvas.create_line(0, 0, 0, screen_height, fill="white", width=1)

            # 绑定鼠标事件
            self.canvas.bind("<Button-1>", self.on_mouse_down)
            self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
            self.canvas.bind("<ButtonRelease-1>", self.on_mouse_up)
            self.canvas.bind("<Motion>", self.on_mouse_move)  # 鼠标移动事件，用于更新十字线

            # 绑定键盘事件
            self.root.bind("<Escape>", self.on_cancel)
            self.root.bind("<FocusOut>", self.on_focus_out)  # 处理失去焦点事件

            # 确保窗口获得焦点
            self.root.focus_force()

            self.root.mainloop()

            # 返回选择的区域
            if (self.start_x is not None and self.end_x is not None and
                    self.start_y is not None and self.end_y is not None):
                # 确保坐标顺序正确
                left = min(self.start_x, self.end_x)
                top = min(self.start_y, self.end_y)
                right = max(self.start_x, self.end_x)
                bottom = max(self.start_y, self.end_y)

                # 检查区域有效性
                if left < right and top < bottom:
                    return (left, top, right, bottom)

            return None

        except Exception as e:
            logging.error(f"选择截图区域时出错: {e}")
            return None

    def on_mouse_down(self, event):
        """鼠标按下事件"""
        # 只有在还没有完成选择时才响应鼠标按下事件
        if not self.selection_made:
            self.drawing = True
            self.start_x = event.x
            self.start_y = event.y
            self.end_x = event.x
            self.end_y = event.y

            # 更新坐标显示
            self.update_coordinates()

    def on_mouse_drag(self, event):
        """鼠标拖拽事件"""
        # 只有在还没有完成选择时才响应鼠标拖拽事件
        if not self.selection_made and self.drawing:
            # 删除之前的选择矩形
            if self.selection_rect:
                self.canvas.delete(self.selection_rect)

            # 更新结束点
            self.end_x = event.x
            self.end_y = event.y

            # 确保坐标在有效范围内
            if self.start_x is not None and self.start_y is not None:
                # 绘制新的选择矩形（明亮的区域表示选中的部分）
                self.selection_rect = self.canvas.create_rectangle(
                    self.start_x, self.start_y,
                    self.end_x, self.end_y,
                    fill='#FFFFFF',  # 使用十六进制颜色值
                    outline='red',
                    width=2
                )

            # 更新坐标显示
            self.update_coordinates()
            
            # 在拖动时也更新十字线位置
            self.on_mouse_move(event)

    def on_mouse_up(self, event):
        """鼠标释放事件"""
        # 只有在还没有完成选择时才响应鼠标释放事件
        if not self.selection_made:
            self.drawing = False
            # 更新结束点
            self.end_x = event.x
            self.end_y = event.y

            # 确保有选择区域
            if (self.start_x is not None and self.end_x is not None and
                self.start_y is not None and self.end_y is not None):
                # 删除之前的选择矩形
                if self.selection_rect:
                    self.canvas.delete(self.selection_rect)

                # 绘制最终的选择矩形（明亮的区域表示选中的部分）
                self.selection_rect = self.canvas.create_rectangle(
                    self.start_x, self.start_y,
                    self.end_x, self.end_y,
                    fill='#FFFFFF',  # 使用十六进制颜色值
                    outline='red',
                    width=2
                )

                # 更新坐标显示
                self.update_coordinates()
                
                # 检查区域是否有效（尺寸大于0）
                width = abs(self.end_x - self.start_x)
                height = abs(self.end_y - self.start_y)
                
                if width > 0 and height > 0:
                    # 区域有效，标记选择已完成并关闭窗口
                    self.selection_made = True
                    self.root.quit()
                    self.root.destroy()

    def on_mouse_move(self, event):
        """鼠标移动事件 - 更新十字线位置"""
        if self.canvas:
            # 更新水平十字线位置
            self.canvas.coords(self.crosshair_h, 0, event.y, self.canvas.winfo_width(), event.y)
            # 更新垂直十字线位置
            self.canvas.coords(self.crosshair_v, event.x, 0, event.x, self.canvas.winfo_height())

    def update_coordinates(self):
        """更新坐标显示"""
        if (self.drawing and self.start_x is not None and self.end_x is not None and
                self.start_y is not None and self.end_y is not None):
            width = abs(self.end_x - self.start_x)
            height = abs(self.end_y - self.start_y)
            # 确保尺寸非负
            width = max(0, width)
            height = max(0, height)
            coord_text = f"区域大小: {width} x {height} 像素"
            self.canvas.itemconfig(self.coord_label, text=coord_text)

    def show_confirmation_dialog(self):
        """显示确认对话框"""
        # 检查是否有有效的选择区域
        if (self.start_x is not None and self.end_x is not None and
                self.start_y is not None and self.end_y is not None):
            # 计算区域尺寸
            width = abs(self.end_x - self.start_x)
            height = abs(self.end_y - self.start_y)

            # 检查区域是否有效（尺寸大于0）
            if width > 0 and height > 0:
                # 直接确认选择，不显示对话框
                self.selection_made = True
                self.root.quit()
                self.root.destroy()
            else:
                # 如果区域尺寸为0，清除选择并提示用户重新选择
                if self.selection_rect:
                    self.canvas.delete(self.selection_rect)
                self.start_x = None
                self.start_y = None
                self.end_x = None
                self.end_y = None
                # 重置坐标显示
                self.canvas.itemconfig(self.coord_label, text="区域大小: 0 x 0 像素")
                # 更新提示信息
                self.canvas.itemconfig("hint", text="选择区域太小，请重新开始拖拽选择区域...")
        else:
            # 如果没有选择区域，提示用户先选择区域
            self.canvas.itemconfig("hint", text="请先拖拽选择一个区域")

    def on_cancel(self, event=None):
        """取消操作"""
        self.start_x = None
        self.start_y = None
        self.end_x = None
        self.end_y = None
        self.root.quit()
        self.root.destroy()

    def on_focus_out(self, event=None):
        """处理失去焦点事件"""
        # 如果窗口失去焦点，重新获取焦点
        if self.root and not self.selection_made:
            self.root.focus_force()
            self.root.attributes('-topmost', True)


# 添加全局变量防止重复截图
_screenshot_in_progress = False


def select_screenshot_region():
    """
    选择截图区域
    
    Returns:
        tuple: 截图区域 (left, top, right, bottom) 或 None
    """
    global _screenshot_in_progress

    # 检查是否已经有截图在进行中
    if _screenshot_in_progress:
        messagebox.showwarning("截图进行中", "已有截图操作正在进行，请先完成当前操作")
        return None

    try:
        # 标记截图开始
        _screenshot_in_progress = True

        selector = ScreenshotSelector()
        result = selector.select_region()
        return result
    finally:
        # 确保标记被重置
        _screenshot_in_progress = False


def capture_screenshot_with_selection(show_overlay=False):
    """
    选择区域并截图
    
    Args:
        show_overlay (bool): 是否在原位置显示置顶截图
    
    Returns:
        PIL.Image: 截图图像 或 None
    """
    global _screenshot_in_progress

    # 注意：这里不设置 _screenshot_in_progress = True，因为实际的截图操作在 select_screenshot_region 中进行
    # 这样可以避免在截图选择过程中重复调用时出现问题

    # 如果需要显示overlay且已有overlay存在，则先关闭它
    if show_overlay:
        try:
            from utils.overlay import ScreenshotOverlay
            if ScreenshotOverlay._current_overlay:
                ScreenshotOverlay._current_overlay.close_overlay()
        except Exception:
            # 忽略错误，继续执行
            pass

    region = select_screenshot_region()
    if region:
        screenshot = capture_screenshot(region)
        if screenshot and show_overlay:
            # 导入置顶显示功能
            try:
                from utils.overlay import show_screenshot_overlay
                # 获取截图区域的左上角坐标作为显示位置
                left, top = region[0], region[1]
                # 直接调用显示函数，避免创建额外的tk主循环
                show_screenshot_overlay(screenshot, (left, top))
            except ImportError:
                logging.warning("无法导入截图置顶显示模块")
        return screenshot
    return None
